package com.xd.clap.utils.convenient;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.xd.clap.commons.SystemConstant;
import com.xd.clap.entity.request.SmsRO;
import com.xd.clap.entity.response.Result;
import com.xd.clap.exception.ClapException;
import com.xd.clap.utils.CodeUtils;
import com.xd.clap.utils.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;

/***
 * @description 代码便捷包
 * @author guanxiangfeng
 * @date 2023/4/18 17:30
 * @params
 * @return
 */
@Component
public class ConvenientUtil {
    private static final Logger log = LoggerFactory.getLogger(com.xd.clap.utils.convenient.ConvenientUtil.class);
    /**工具类注入bean
     * @author guanxiangfeng
     * @date 2023/4/18 17:30
     */
    @Autowired
    private RedisUtil redisUtil;

    private static com.xd.clap.utils.convenient.ConvenientUtil convenientUtil ;
    @PostConstruct
    public void init() {
        convenientUtil = this;
        convenientUtil.redisUtil= this.redisUtil;

    }

    /**
      *计数当前时间到当天最后时间 的间隔时间差
      * @param unit 计数时间类型 DateUnit.SECOND 秒
      * @return long
     * @author guanxiangfeng
     * @date 2023/4/18 17:30
      */
    public static long countEndTime(DateUnit unit){
        DateTime time = DateUtil.date();
        Date beginOfDay = DateUtil.endOfDay(time);
        long betweenDay = DateUtil.between(time, beginOfDay, unit);
        return betweenDay;
    }

    /**
     *验证验证码是否合理
     * @param toVerifyCode
     * @return void
     * @author guanxiangfeng
     * @date 2023/4/18 17:30
     */
    public static void verifyCode(String toVerifyCode, String merchantPhone){
        //从redis中取出验证码
        SmsRO verifyCode = (SmsRO) convenientUtil.redisUtil.get(SystemConstant.PHONE_VERIFY_CODE + merchantPhone);
        //1.判定验证码是否过期
        if (ObjectUtil.isEmpty(verifyCode))
        {
            throw new ClapException(100,"验证码已过期");
        }
        //2.验证 验证码是否一致
        if (!ObjectUtil.equals(verifyCode.getCode(),toVerifyCode)){
            throw new ClapException(100,"验证码错误");
        }
        //3.二次验证 前后电话号码一致
        if (!ObjectUtil.equals(verifyCode.getMerchantPhone(),merchantPhone)){
            throw new ClapException(100,"验证码前后号码不一致");
        }
    }
    /**
      *验证码发送 防止多次发送
      *次数限定 递增
      * @param merchantPhone
      * @return String
     * @author guanxiangfeng
     * @date 2023/4/18 17:30
      */
    public synchronized static String sendSms(String merchantPhone) {
        Integer useNum = (Integer) convenientUtil.redisUtil.get(SystemConstant.PHONE_NUM_CODE + merchantPhone);
        //限制验证码发送数量 一天为期限 不可超过 10次
        if (ObjectUtil.isEmpty(useNum)){
            //redis 不存在验证码信息
            //1.调用工具包 发送验证码
            //2.把返回的验证码 放进 redis中 90秒
            convenientUtil.redisUtil.set(SystemConstant.PHONE_VERIFY_CODE+merchantPhone,new SmsRO(merchantPhone, CodeUtils.getCode(merchantPhone)),SystemConstant.NUM_90);
            //redis已存在 则++size
            convenientUtil.redisUtil.incr(SystemConstant.PHONE_NUM_CODE+merchantPhone,SystemConstant.NUM_ONE);
            //设置有效期为当天
            convenientUtil.redisUtil.expire(SystemConstant.PHONE_NUM_CODE+merchantPhone,countEndTime(DateUnit.SECOND));
        }else {
//            发送次数大于10次 一天停止在发验证码
            if (useNum>=SystemConstant.NUM_TEN) {
                throw new ClapException(100, "验证码发送次数已用完");
            }else {
                //redis已存在 则++size
                convenientUtil.redisUtil.incr(SystemConstant.PHONE_NUM_CODE+merchantPhone,SystemConstant.NUM_ONE);
                //设置有效期当天
                convenientUtil.redisUtil.expire(SystemConstant.PHONE_NUM_CODE+merchantPhone,countEndTime(DateUnit.SECOND));
                //发送短信 放入缓存中
                convenientUtil.redisUtil.set(SystemConstant.PHONE_VERIFY_CODE+merchantPhone,new SmsRO(merchantPhone,CodeUtils.getCode(merchantPhone)),SystemConstant.NUM_90);
            }
        }
        return "验证码已发送";
    }
    /**
      *次数限定 递增
      * @param redisKey
      * @param number
      * @return void
     * @author guanxiangfeng
     * @date 2023/4/18 17:30
      */
    public static void limitedNumber(String redisKey,Integer number){
        //为了防止并发和重复 使用递增
        //如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCR 操作
        //限制次数 当天为期限 不可超过 number次
        Integer useNumber = (Integer) convenientUtil.redisUtil.get(redisKey);
        if (ObjectUtil.isEmpty(useNumber)){
            //如果为空 则直接放置数量一
            convenientUtil.redisUtil.incr(redisKey,SystemConstant.NUM_ONE);
            //设置有效期当天有效
            convenientUtil.redisUtil.expire(redisKey,countEndTime(DateUnit.SECOND));
        }else {
            //获取已发送次数
            //发送次数大于number次 当天内停止在发验证码
            if (useNumber>=number) {
                throw new ClapException(100, "使用次数已用完");
            }else {
                //redis已存在 则++size
                convenientUtil.redisUtil.incr(redisKey,SystemConstant.NUM_ONE);
                //设置有效期当天有效
                convenientUtil.redisUtil.expire(redisKey,countEndTime(DateUnit.SECOND));

            }
        }

    }

}

